package com.hi.flow.controller;

import com.hi.flow.utils.FlowState;
import com.hi.flow.utils.FlowUtil;
import com.hi.flow.vo.HistoryVo;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.util.*;

/**
 *
 * @author xj
 * @date 2020/06/16
 */
@Controller
public class ExpenseController {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private HistoryService historyService;

    /**
     * 添加审批
     *
     * @param companyId 公司ID

     */
    @RequestMapping(value = "/add")
    @ResponseBody
    public String addExpense(String companyId) {
        //启动流程
        HashMap<String, Object> map = new HashMap<>();
        map.put("companyId", companyId);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("approve", map);
        return "提交成功.流程Id为：" + processInstance.getId();
    }

    /**
     * 提交
     * @param companyId
     * @return
     */
    @RequestMapping(value = "/commitInfo")
    @ResponseBody
    public String commitInfo(String companyId,String manager) {

        //查找该公司的审核流程
        Task task = taskService.createTaskQuery().taskAssignee(companyId).singleResult();

        if (task == null)
            throw new RuntimeException("流程不存在");

        HashMap<String, Object> map = new HashMap<>();
        map.put("approved", true);
        map.put("manager", manager);
        //提交审核
        taskService.complete(task.getId(), map);
        return "processed ok!";
    }


    /**
     * 运营审核
     * @param processId
     * @param approved
     * @param manager
     * @return
     */
    @RequestMapping(value = "/approve")
    @ResponseBody
    public String approve(String processId, String approved,String manager) {

        //查询审核任务
        Task task =  taskService.createTaskQuery().taskCandidateGroup(manager).processInstanceId(processId).singleResult();

        if (task == null)
            throw new RuntimeException("流程不存在");

        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("approved", approved.equals("1") ? true : false);
        map.put("manager", manager);
        taskService.complete(task.getId(), map);
        return "processed ok!";
    }



    /**
     * 获取审批管理列表
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(String userId,String type,String group) {
        List<Task> tasks = new ArrayList<>();
        //组查询时
        if("1".equals(type)){
            tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        }
        //单用户查询时
        else{
            tasks = taskService.createTaskQuery().taskCandidateGroup(group).list();
        }
        return tasks.toString();
    }


    /**
     * 查看历史流程记录
     *
     * @param processId
     * @return
     */
    @RequestMapping(value ="/historyList")
    @ResponseBody
    public Object getHistoryList(String processId) {
        List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processId).finished().orderByHistoricActivityInstanceEndTime().asc().list();
        return historicActivityInstances;
    }

    /**
     * 查看历史流程记录
     *
     * @param processId
     * @return
     */
    @GetMapping("history")
    @ResponseBody
    public List<HistoryVo> getHistory(String processId) throws Exception{
        List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processId).finished().orderByHistoricActivityInstanceEndTime().asc().list();
        if(historicActivityInstances.isEmpty())
            throw new Exception(FlowUtil.HISTORY_NULL_ERROR);

        List<HistoryVo> historyVos = new ArrayList<>();
        int index = 0;
        for(HistoricActivityInstance historicActivityInstance : historicActivityInstances){
            HistoryVo historyVo = new HistoryVo();
            DateFormat df = DateFormat.getDateTimeInstance();

            if(FlowState.CUSTOM_START.equals(historicActivityInstance.getActivityId())){
                historyVo.setTime(df.format(historicActivityInstance.getEndTime()));
                historyVo.setTitle(FlowUtil.FILL_INFO);
                historyVos.add(historyVo);
            }
            if(FlowState.CUSTOM_COMMIT.equals(historicActivityInstance.getActivityId())){
                historyVo.setTime(df.format(historicActivityInstance.getEndTime()));
                    historyVo.setTitle(FlowUtil.COMMIT_INFO);
                historyVos.add(historyVo);
            }

            if(FlowState.BUSINESS_APPROVE.equals(historicActivityInstance.getActivityId())){
                historyVo.setTime(df.format(historicActivityInstance.getEndTime()));
                if(index < historicActivityInstances.size() - 2 && FlowState.TASK_END.equals(historicActivityInstances.get(index+2).getActivityId())){
                    historyVo.setTitle(FlowUtil.APPROVE_PASS);
                }
                else {
                    historyVo.setTitle(FlowUtil.APPROVE_UNPASS);
                }
                historyVos.add(historyVo);
            }
            index++;
        }
        return historyVos;
    }


    /**
     * 生成流程图
     *
     * @param processId 任务ID
     */
    @RequestMapping(value = "/processDiagram")
    public void processDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
        //1.获取当前的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        String processDefinitionId = null;
        List<String> activeActivityIds = null;
        //2.获取所有的历史轨迹对象
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processId).list();
        Map<String, HistoricActivityInstance> hisActivityMap = new HashMap<>();
        list.forEach(historicActivityInstance -> {
            if (!hisActivityMap.containsKey(historicActivityInstance.getActivityId())) {
                hisActivityMap.put(historicActivityInstance.getActivityId(), historicActivityInstance);
            }
        });
        //3. 获取流程定义id和高亮的节点id
        if (processInstance != null) {
            //3.1. 正在运行的流程实例
            processDefinitionId = processInstance.getProcessDefinitionId();
            activeActivityIds = runtimeService.getActiveActivityIds(processId);
        } else {
            //3.2. 已经结束的流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
            processDefinitionId = historicProcessInstance.getProcessDefinitionId();
            activeActivityIds = new ArrayList<>();
            List<EndEvent> endEvents = findEndFlowElement(processDefinitionId);
            List<String> finalActiveActivityIds = activeActivityIds;
            endEvents.forEach(endEvent -> {
                if (hisActivityMap.containsKey(endEvent.getId())) {
                    finalActiveActivityIds.add(endEvent.getId());
                }
            });
        }
        //4. 获取流程定义的所有节点信息
        List<String> highLightedFlows = new ArrayList<>();
        //6. 获取bpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        //7. 生成图片流
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png",
                activeActivityIds, highLightedFlows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    public List<EndEvent> findEndFlowElement(String processDefId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
        if (bpmnModel != null) {
            Process process = bpmnModel.getMainProcess();
            return process.findFlowElementsOfType(EndEvent.class);
        } else {
            return null;
        }
    }



}
